package com.atguigu.dga230315.governance.assess.storage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga230315.governance.assess.Assessor;
import com.atguigu.dga230315.governance.bean.AssessParam;
import com.atguigu.dga230315.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga230315.meta.bean.TableMetaInfo;
import com.atguigu.dga230315.meta.constant.MetaConst;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

//是否为相似表
@Component("TABLE_SIMILAR")
public class TableSimilarAssess extends Assessor {
    @Override
    protected void assess(GovernanceAssessDetail assessDetail, AssessParam assessParam) throws ParseException {
        //干嘛：针对考评的表 获取到字段 然后和其他的表字段对比，看重复度是否超过阈值。
        //特殊点： 1.ods层的表不参与考评
        //       2.对比同层的表
        //       3.不对比自己表

        //思路：1.获取考评表的所有字段
        //     2.获取其他表的每张表的所有字段
        //     3.一张表一张表对比
        //     4.从指标参数表中获取阈值
        //     5.将相同的占比和阈值对比看是否相似

        //1.获取考评表的所有字段
        TableMetaInfo curTableMetaInfo = assessParam.getTableMetaInfo();
        String curColNameJsonStr = curTableMetaInfo.getColNameJson();
        //将JSON字符串转为List<JsonObject>   说明:因为获取到的字符串里面套了多个json所以先转为集合
        List<JSONObject> curJsonObjList = JSON.parseArray(curColNameJsonStr, JSONObject.class);
        //获取自己的库
        String curSchemaName = curTableMetaInfo.getSchemaName();
        String curTableName = curTableMetaInfo.getTableName();
        //考评表的全表名
        String curFullTableName = curSchemaName + "." + curTableName;
        //考评表的层级
        String curDwLevel = curTableMetaInfo.getTableMetaInfoExtra().getDwLevel();


        //2.获取到其他所有的表
        Map<String, TableMetaInfo> otherTableMetaInfoMap = assessParam.getFullNameToTableMetaInfoMap();

        //创建List集合用来存放所有与考评表相似的表
        ArrayList<String> similarFullTableNameList = new ArrayList<>();


        //遍历获取到每张表
        for (Map.Entry<String, TableMetaInfo> tableMetaInfoEntry : otherTableMetaInfoMap.entrySet()) {
            TableMetaInfo otherTableMetaInfo = tableMetaInfoEntry.getValue();

            //对比表的全表名
            String otherFullTableName = tableMetaInfoEntry.getKey();
            //对比表的层级
            String otherDwLevel = otherTableMetaInfo.getTableMetaInfoExtra().getDwLevel();

            if (!curDwLevel.equals(MetaConst.DW_LEVEL_ODS)//1.ods层的表不参与考评
                    && curDwLevel.equals(otherDwLevel)   //      2.对比同层的表
                    && !curFullTableName.equals(otherFullTableName)   //      3.不对比自己表
            ) {
                //对比两个表的字段是否相同

                //首先获取到对比表的所有字段
                String otherColNameJsonStr = otherTableMetaInfo.getColNameJson();
                List<JSONObject> otherJsonObjList = JSON.parseArray(otherColNameJsonStr, JSONObject.class);

                //创建计数器 (相同字段的个数)
                Integer simliarCount = 0;

                //进行双层for循环遍历两个表的所有字段
                for (JSONObject curObj : curJsonObjList) {
                    for (JSONObject otherObj : otherJsonObjList) {
                        //提取字段名 根据字段名判断字段是和否相同
                        String curColName = curObj.getString("name");
                        String otherColName = otherObj.getString("name");
                        if (curColName.equals(otherColName)){
                            //字段相同
                            simliarCount++;
                        }
                    }
                }


                //等两张表所有字段都判断完毕之后，然后对比这两张表是否相似
                //先计算考评表相同字段的占比
                //获取考评表所有字段的个数
                int curTableColTotal = curJsonObjList.size();

                BigDecimal ratio = BigDecimal.valueOf(simliarCount).divide(BigDecimal.valueOf(curTableColTotal), 2, RoundingMode.HALF_UP).movePointRight(2);

                //获取指标参数中的阈值
                String metricParamsJson = assessParam.getGovernanceMetric().getMetricParamsJson();
                JSONObject percentJSONObj = JSON.parseObject(metricParamsJson);
                BigDecimal percent = percentJSONObj.getBigDecimal("percent");

                if (ratio.compareTo(percent)>0){
                    similarFullTableNameList.add(otherFullTableName);
                    //指定分数
                    assessDetail.setAssessScore(BigDecimal.ZERO);
                    assessDetail.setAssessProblem("存在相似表");
                }
            }
        }

        //设置备注
        if (!similarFullTableNameList.isEmpty()){
            assessDetail.setAssessComment(similarFullTableNameList.toString());
        }
    }
}
